<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    html,body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      background: #001122;
      /* svg是个内联元素,这里,为了防止出现滚动条,将字体置为0 */
      line-height: 0;
      font-size: 0;
    }
  </style>
</head>
<body>
  <svg width="100%" height="100%"
    viewBox="-400 -300 800 600"
    perserveAspectRatio="xMidYMid slice"
  >
    <!--
      defs 这里是 定义 的意思
      就相当于function(){} let var ...
    -->
    <defs>
      <polygon id="star" points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" fill="white"></polygon>
    </defs>

    <g id="real">
      <!-- 月亮 -->
      <g id="moon-group">
        <mask id="moon-mask">
          <circle cx="-250" cy="-150" r="100" fill="white"></circle>
          <circle cx="-200" cy="-200" r="100" fill="black"></circle>
        </mask>
        <circle cx="-250" cy="-150" r="100" fill="yellow" mask="url(#moon-mask)"></circle>
      </g>

      <!-- 星星 -->
      <g id="star-group"></g>

      <!-- 灯塔 -->
      <!-- 没错,defs会受外面<g>影响 -->
      <g id="light-tower" transform="translate(250, 0)">
        <defs>
          <linearGradient id="tower" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0" stop-color="#999"></stop>
            <stop offset="1" stop-color="#333"></stop>
          </linearGradient>
          <radialGradient id="light" cx="0.5" cy="0.5" r="0.5">
            <stop offset="0" stop-color="rgba(255,255,255,0.8)"></stop>
            <stop offset="1" stop-color="rgba(255,255,255,0)"></stop>
          </radialGradient>
          <clipPath id="light-clip">
            <polygon points="0 0 -400 -15 -400 15" fill="rgba(255,0,0,0.5)">
              <animateTransform
                attributeName="transform"
                attributeType="XML"
                type="rotate"
                from="0"
                to="360"
                dur="10s"
                repeatCount="indefinite"
              ></animateTransform>
            </polygon>
            <circle cx="0" cy="0" r="2"></circle>
          </clipPath>
        </defs>

        <!-- 灯塔 -->
        <polygon points="0 0 5 50 -5 50" fill="url(#tower)"></polygon>

        <!-- 灯塔照出的光 -->
        <!-- https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute/clip-path
          元素的表现属性 clip-path 为其定义或关联一条剪切路径

          作为一种表现属性，clip-path 可以用于任何元素，不过效果最明显的是下列十九种元素：<a>, <circle>, <clipPath>, <ellipse>, <g>, <glyph>, <image>, <line>, <marker>, <mask>, <path>, <pattern>, <polygon>, <polyline>, <rect>, <svg>, <symbol>, <text>, <use>
        -->
        <ellipse cx="0" cy="0" rx="300" ry="100" fill="url(#light)" clip-path="url(#light-clip)"></ellipse>
      </g>
    </g>
    <g id="reflact" transform="translate(0 50)" mask="url(#fading)">
      <defs>
        <linearGradient id="fade" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stop-color="rgba(255,255,255,.3)"></stop>
          <stop offset="0.5" stop-color="rgba(255,255,255,0)"></stop>
        </linearGradient>
        <mask id="fading">
          <rect x="-400" y="0" width="800" height="300" fill="url(#fade)"></rect>
        </mask>
      </defs>
      <!-- use不能加mask -->
      <use xlink:href="#real" transform="scale(1, -1) translate(0 -50)"></use>
    </g>
    <line x1="-400" y1="50" x2="400" y2="50" stroke="white"></line>
  </svg>
  <script>
    const SVG_NS = 'http://www.w3.org/2000/svg';
    const XLINK_NS = 'http://www.w3.org/1999/xlink';
    const paper = document.querySelector('svg');

    function random(min, max) {
      return min + (max - min) * Math.random();
    }

    function use(origin) {
      const _use = document.createElementNS(SVG_NS, 'use');
      _use.setAttributeNS(XLINK_NS, 'xlink:href', `#${origin.id}`); /** 设置引用地址, 要引用哪个图形,就 xlink:href="#那个图形的id"*/
      return _use;
    }

    function renderStar() {
      const starRef = document.getElementById('star');
      const starGroup = document.getElementById('star-group');
      let starCount = 500;
      let star;

      while (starCount--) {
        star = use(starRef);
        star.setAttribute('opacity', random(0.1, 0.4));
        star.setAttribute('transform', `translate(${random(-400, 400)},${random(-300, 300)}) scale(${random(0.1,0.6)})`);
        starGroup.appendChild(star);
      }
    }

    renderStar();
  </script>
</body>
</html>
